﻿
Public Interface iInvokeable
    Function invoke(ByVal ctx As context) As Boolean
End Interface

Public Interface iInvokeableWithOutput
    Function invoke(ByVal ctx As context, ByRef output As bare_variable) As Boolean
End Interface

Public Interface iInvokeableBetweenContext
    Function invoke(ByVal dest As context, ByVal src As context) As Boolean
End Interface

#If RETIRED Then
Public Interface iInvokeableBetweenContextWithOutput
    Function invoke(ByVal dest As context, ByVal src As context, ByRef output As bare_variable) As Boolean
End Interface
#End If

Public Interface iInvokeableWithParameter(Of T)
    Function invoke(ByVal ctx As context, ByVal obj As T) As Boolean
End Interface

Public Interface iInvokeableWithMapping
    Function invoke(ByVal ctx As context, ByVal m As iParametersMapping) As Boolean
End Interface

Public Interface iInvokeableBetweenContextWithMapping
    Function invoke(ByVal dest As context, ByVal src As context, ByVal m As iParametersMapping) As Boolean
End Interface

'define the interface between .net code & elpmis script
Public Interface iParameters
    Inherits iInvokeable
End Interface

'define the interface between context
Public Interface iParametersBetweenContext
    Inherits iInvokeableBetweenContext
End Interface

Public Interface iParametersWithMapping
    Inherits iInvokeableWithMapping
End Interface

Public Interface iParametersBetweenContextWithMapping
    Inherits iInvokeableBetweenContextWithMapping
End Interface

Public Interface iParametersMapping
    Function size() As Int64
    Default ReadOnly Property at(ByVal index As Int64) As String
End Interface

Public Interface iVariableFinder(Of T)
    Function find(ByVal ctx As context, ByVal name As String, ByRef output As T) As Boolean
    Function find(ByVal ctx As context, ByVal name As String) As T
End Interface

Public Interface iViewSource
    Function scriptAll() As String
    Function scriptSource() As String
    Function scriptStart() As Int64
    Function scriptEnd() As Int64
End Interface

Public Class iParseable
    Implements iViewSource

    Protected Delegate Function parseImplDelegate(Of T As iParseable)(ByVal script As String, ByRef index As Int64, _
                                                                      ByRef output As T) As Boolean
    Private sv As sourceViewer = Nothing

    Public Function scriptAll() As String Implements iViewSource.scriptAll
        Return sv.get()
    End Function

    Public Function scriptSource() As String Implements iViewSource.scriptSource
        Return sv.script()
    End Function

    Public Function scriptStart() As Int64 Implements iViewSource.scriptStart
        Return sv.start()
    End Function

    Public Function scriptEnd() As Int64 Implements iViewSource.scriptEnd
        Return sv.end()
    End Function

    Protected Sub setsourceImpl(ByVal src As String, ByVal start As Int64, ByVal [end] As Int64)
        kickLeftRightBlank(src)
        sv.set(src, start, [end])
    End Sub

    Protected Overridable Sub setsource(ByVal script As String, ByVal start As Int64, ByVal [end] As Int64)
        setsourceImpl(strmid(script, start, [end] - start), start, [end])
    End Sub

    Protected Shared Function parsebase(Of T As iParseable)(ByVal script As String, ByRef _index As Int64, _
                                                            ByRef output As T, _
                                                            ByVal p As parseImplDelegate(Of T), _
                                                            Optional ByVal setsource As Boolean = True) As Boolean
        assert(Not p Is Nothing, "p is nothing.")
        Dim index As Int64
        index = _index
        If p(script, index, output) Then
            assert(Not output Is Nothing, "output is nothing after parseImpl returns true.")
            If setsource Then
                output.setsource(script, _index, index)
            End If
            _index = index
            Return True
        Else
            Return False
        End If
    End Function

    Protected Sub New()
        sv = New sourceViewer()
    End Sub
End Class

'all the public functions should call invokebase, otherwise directly invokeImpl
Public MustInherit Class iScript
    Inherits iParseable

    Protected Overridable Function invokeImpl(ByVal ctx As context) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(ByVal ctx As context, ByRef output As bare_variable) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(ByVal dest As context, ByVal src As context) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(ByVal dest As context, ByVal src As context, _
                                              ByRef output As bare_variable) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(Of T)(ByVal ctx As context, ByRef obj As T) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(Of T)(ByVal ctx As context, ByRef output As bare_variable, _
                                                    ByRef obj As T) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(Of T)(ByVal dest As context, ByVal src As context, _
                                                    ByRef obj As T) As Boolean
        Return True
    End Function

    Protected Overridable Function invokeImpl(Of T)(ByVal dest As context, ByVal src As context, _
                                                    ByRef output As bare_variable, ByRef obj As T) As Boolean
        Return True
    End Function

    Protected Sub invokefailed(Optional ByVal additionaljump As Int32 = 1)
        If Not isemptystring(scriptSource()) Then
            'jump invokefailed & invokebase
            raiseError(character.tab + "@" + scriptAll(), errorHandle.errorType.user, _
                       additionaljump:=additionaljump + 1)
        End If
    End Sub

    Protected Function invokebase(ByVal ctx As context) As Boolean
        If Not invokeImpl(ctx) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(ByVal ctx As context, ByRef output As bare_variable) As Boolean
        If Not invokeImpl(ctx, output) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(ByVal dest As context, ByVal src As context) As Boolean
        If Not invokeImpl(dest, src) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(ByVal dest As context, ByVal src As context, _
                                  ByRef output As bare_variable) As Boolean
        If Not invokeImpl(dest, src, output) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(Of T)(ByVal ctx As context, ByRef obj As T) As Boolean
        If Not invokeImpl(ctx, obj) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(Of T)(ByVal ctx As context, ByRef output As bare_variable, ByRef obj As T) As Boolean
        If Not invokeImpl(ctx, output, obj) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(Of T)(ByVal dest As context, ByVal src As context, ByRef obj As T) As Boolean
        If Not invokeImpl(dest, src, obj) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function

    Protected Function invokebase(Of T)(ByVal dest As context, ByVal src As context, _
                                  ByRef output As bare_variable, ByRef obj As T) As Boolean
        If Not invokeImpl(dest, src, output, obj) Then
            invokefailed()
            Return False
        Else
            Return True
        End If
    End Function
End Class

#If Not PocketPC AndAlso Not Smartphone Then
Public Class iContextpool
    Inherits pool2(Of context, _false, _false)
End Class
#Else
Public Class iContextpool
    Inherits pool2(Of context, _true, _false)
End Class
#End If
